﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.IO;
using System.Net;
using System.Net.Sockets;

namespace YoSunSDK
{
    /// <summary>
    /// 消息类型
    /// </summary>
    public enum CMDTYPE
    {
        /// <summary>
        /// 图片上传消息
        /// </summary>
        CMD_UPLOAD = (byte)1,
        /// <summary>
        /// 报警设备注册消息
        /// </summary>
        CMD_REG_ALARMDEV = (byte)2,
        /// <summary>
        /// 设备/平台注册消息
        /// </summary>
        CMD_REG_DEV = (byte)6,
        /// <summary>
        /// 设备状态
        /// </summary>
        CMD_DEV_STATUS = (byte)7,
        /// <summary>
        /// 上传结束应答消息
        /// </summary>
        CMD_UPLOAD_ACK = (byte)9
    }

    [StructLayoutAttribute(LayoutKind.Sequential)]
    public struct MsgHead
    {
        /// <summary>
        /// 消息体长度（不含消息头）
        /// </summary>
        public ushort len;

        /// <summary>
        /// 消息类型
        /// </summary>
        public byte type;

        /// <summary>
        /// 消息版本1-6
        /// </summary>
        public byte ver;
    }

    [StructLayoutAttribute(LayoutKind.Sequential)]
    public struct MsgRegDev
    {
        /// <summary>
        /// client的监听端口.自己定义
        /// </summary>
        public ushort port;

        /// <summary>
        /// probType=1
        /// </summary>
        public byte probType;

        /// <summary>
        /// pasType=1
        /// </summary>
        public byte pasType;

        /// <summary>
        /// sndPic=1
        /// </summary>
        public byte sndPic;

        /// <summary>
        /// pasNum=0
        /// </summary>
        public byte pasNum;
    }

    [StructLayoutAttribute(LayoutKind.Sequential)]
    public struct MsgAck
    {
        /// <summary>
        /// op=1表示注册成功op=2表示注册失败
        /// </summary>
        public byte op;

        /// <summary>
        /// reserved1
        /// </summary>
        public byte reserved1;

        /// <summary>
        /// reserved2
        /// </summary>
        public byte reserved2;

        /// <summary>
        /// reserved3
        /// </summary>
        public byte reserved3;
    }

    [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct MsgUpload
    {
        public uint bitvector1;

        /// <summary>
        /// 日期，按1970年以来的秒数计算
        /// </summary>
        public uint date;

        public ushort bitvector2;

        /// <summary>
        /// 速度，15-999
        /// </summary>
        public ushort speed;

        /// <summary>
        /// 路口代码
        /// </summary>
        public ushort pasCode;

        public ushort bitvector3;

        /// <summary>
        /// 车牌后6位字母
        /// </summary>
        [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 6, ArraySubType = UnmanagedType.I1)]
        public char[] plate2;

        public uint bitvector4;

        public uint bitvector5;

        /// <summary>
        /// 违章原因，具体定义见后面
        /// </summary>
        public ushort reason;

        /// <summary>
        /// productType
        /// </summary>
        public byte productType;

        /// <summary>
        /// 转向代码: 1 左拐，2 直行，3 右拐，4 直左，5 直右
        /// </summary>
        public byte turnCode;

        /// <summary>
        /// picCount，图片总张数
        /// </summary>
        public byte picCount;

        /// <summary>
        /// picOrder，当前图片序号
        /// </summary>
        public byte picOrder;

        /// <summary>
        /// 闯红灯时间，精确到0.1秒
        /// </summary>
        public ushort redLightTime;

        /// <summary>
        /// ta1
        /// </summary>
        public ushort ta1;

        /// <summary>
        /// ta2
        /// </summary>
        public ushort ta2;

        /// <summary>
        /// picType，是否闯红灯
        /// </summary>
        public byte picType;

        /// <summary>
        /// 是否逆行，0 正常, 1 逆行
        /// </summary>
        public byte state;

        /// <summary>
        /// 存储设备 ip地址
        /// </summary>
        [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 16, ArraySubType = UnmanagedType.I1)]
        public char[] ip;

        /// <summary>
        /// 图片存放路径
        /// </summary>
        [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 256, ArraySubType = UnmanagedType.I1)]
        public char[] path;

        /// <summary>
        /// 车牌小图片文件大小：0 无车牌，其它 车牌大小
        /// </summary>
        public uint plateSize;

        /// <summary>
        /// 红名单告警： 0 不是，1是
        /// </summary>
        public byte vip;

        /// <summary>
        /// 模糊车牌告警： 0不是，1是
        /// </summary>
        public byte fuzzy;

        /// <summary>
        /// 布控信息，utf8编码
        /// </summary>
        [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 256, ArraySubType = UnmanagedType.I1)]
        public char[] bkInfo;

        /// <summary>
        /// 区域代码
        /// </summary>
        [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 8, ArraySubType = UnmanagedType.I1)]
        public char[] areaCode;

        /// <summary>
        /// 车身颜色
        /// </summary>
        public byte vbColor;

        /// <summary>
        /// 图片数据长度
        /// </summary>
        public uint fileSize
        {
            get
            {
                return ((uint)((this.bitvector1 & 16777215u)));
            }
            set
            {
                this.bitvector1 = ((uint)((value | this.bitvector1)));
            }
        }

        /// <summary>
        /// 方向：01-由东向西,02-由东向南,03-由东向北,04-由南向北,05-由南向西,06-由南向东,;07-由西向东,08-由西向北,09-由西向南,10-由北向南,11-由北向东,12-由北向西,13-进城,14-出城
        /// </summary>
        public uint direction
        {
            get
            {
                return ((uint)(((this.bitvector1 & 251658240u)
                            / 16777216)));
            }
            set
            {
                this.bitvector1 = ((uint)(((value * 16777216)
                            | this.bitvector1)));
            }
        }
        /// <summary>
        /// 车道编号
        /// </summary>
        public uint lane
        {
            get
            {
                return ((uint)(((this.bitvector1 & 4026531840u)
                            / 268435456)));
            }
            set
            {
                this.bitvector1 = ((uint)(((value * 268435456)
                            | this.bitvector1)));
            }
        }
        /// <summary>
        /// 整个红灯时间，精确到秒
        /// </summary>
        public ushort redLight
        {
            get
            {
                return ((ushort)((this.bitvector2 & 1023u)));
            }
            set
            {
                this.bitvector2 = ((ushort)((value | this.bitvector2)));
            }
        }

        /// <summary>
        /// 设备类型：31-高清电子警察 32-高清卡口型电子警察33-高清卡口,34-高清固定超速,35-高清移动超速，36-高清单行线逆行
        /// </summary>
        public ushort device
        {
            get
            {
                return ((ushort)(((this.bitvector2 & 64512u)
                            / 1024)));
            }
            set
            {
                this.bitvector2 = ((ushort)(((value * 1024)
                            | this.bitvector2)));
            }
        }
        /// <summary>
        /// 限速值
        /// </summary>
        public ushort threshold
        {
            get
            {
                return ((ushort)((this.bitvector3 & 511u)));
            }
            set
            {
                this.bitvector3 = ((ushort)((value | this.bitvector3)));
            }
        }

        /// <summary>
        /// 车牌首字母代码，具体定义见后面
        /// </summary>
        public ushort plate1
        {
            get
            {
                return ((ushort)(((this.bitvector3 & 65024u)
                            / 512)));
            }
            set
            {
                this.bitvector3 = ((ushort)(((value * 512)
                            | this.bitvector3)));
            }
        }
        /// <summary>
        /// 车辆长度，单位cm
        /// </summary>
        public uint carLen
        {
            get
            {
                return ((uint)((this.bitvector4 & 4095u)));
            }
            set
            {
                this.bitvector4 = ((uint)((value | this.bitvector4)));
            }
        }

        /// <summary>
        /// 车牌颜色：1 蓝色，2 黑色，3 黄色，4 白色，
        /// </summary>
        public uint color
        {
            get
            {
                return ((uint)(((this.bitvector4 & 258048u)
                            / 4096)));
            }
            set
            {
                this.bitvector4 = ((uint)(((value * 4096)
                            | this.bitvector4)));
            }
        }

        /// <summary>
        /// 超速比：1 0-20%，2 20%-50%, 3 50%-70%, 4 70%以上
        /// </summary>
        public uint overspeed
        {
            get
            {
                return ((uint)(((this.bitvector4 & 66846720u)
                            / 262144)));
            }
            set
            {
                this.bitvector4 = ((uint)(((value * 262144)
                            | this.bitvector4)));
            }
        }

        /// <summary>
        /// writeout，是否导出
        /// </summary>
        public uint writeout
        {
            get
            {
                return ((uint)(((this.bitvector4 & 469762048u)
                            / 67108864)));
            }
            set
            {
                this.bitvector4 = ((uint)(((value * 67108864)
                            | this.bitvector4)));
            }
        }


        /// <summary>
        /// 是否已处罚：0未处罚，1已处罚
        /// </summary>
        public uint punish
        {
            get
            {
                return ((uint)(((this.bitvector4 & 3758096384u)
                            / 536870912)));
            }
            set
            {
                this.bitvector4 = ((uint)(((value * 536870912)
                            | this.bitvector4)));
            }
        }

        /// <summary>
        /// 超速比: 在限速值上放宽范围比例
        /// </summary>
        public uint osratio
        {
            get
            {
                return ((uint)((this.bitvector5 & 127u)));
            }
            set
            {
                this.bitvector5 = ((uint)((value | this.bitvector5)));
            }
        }
        /// <summary>
        /// 抓拍位置: 1-车头，2-侧面, 3-车尾,4-顶部
        /// </summary>
        public uint capPos
        {
            get
            {
                return ((uint)(((this.bitvector5 & 1920u)
                            / 128)));
            }
            set
            {
                this.bitvector5 = ((uint)(((value * 128)
                            | this.bitvector5)));
            }
        }
        /// <summary>
        /// recStatus，识别状态
        /// </summary>
        public uint recStatus
        {
            get
            {
                return ((uint)(((this.bitvector5 & 30720u)
                            / 2048)));
            }
            set
            {
                this.bitvector5 = ((uint)(((value * 2048)
                            | this.bitvector5)));
            }
        }
        /// <summary>
        /// preassign，违章原因
        /// </summary>
        public uint preassign
        {
            get
            {
                return ((uint)(((this.bitvector5 & 4294934528u)
                            / 32768)));
            }
            set
            {
                this.bitvector5 = ((uint)(((value * 32768)
                            | this.bitvector5)));
            }
        }

        /// <summary>
        /// 生成友上结构体
        /// </summary>
        /// <returns>友上结构体</returns>
    }

    /// <summary>
    /// 注册
    /// </summary>
    [StructLayoutAttribute(LayoutKind.Sequential)]
    public struct YoSunRegDev_t
    {
        /// <summary>
        /// client的监听端口.自己定义
        /// </summary>
        public UInt16 port;

        /// <summary>
        /// probType=1
        /// </summary>
        public byte probType;

        /// <summary>
        /// pasType=1
        /// </summary>
        public byte pasType;

        /// <summary>
        /// sndPic=1
        /// </summary>
        public byte sndPic;

        /// <summary>
        /// pasNum=0
        /// </summary>
        public byte pasNum;
    }

    /// <summary>
    /// 反馈消息
    /// </summary>
    [StructLayoutAttribute(LayoutKind.Sequential)]
    public struct YoSunAck_t
    {
        /// <summary>
        /// op=1表示注册成功op=2表示注册失败
        /// </summary>
        public byte op;

        /// <summary>
        /// reserved1
        /// </summary>
        public byte reserved1;

        /// <summary>
        /// reserved2
        /// </summary>
        public byte reserved2;

        /// <summary>
        /// reserved3
        /// </summary>
        public byte reserved3;
    }

    /// <summary>
    /// 友上协议的消息头
    /// </summary>
    [StructLayoutAttribute(LayoutKind.Sequential)]
    public struct YoSunHead_t
    {
        /// <summary>
        /// uint16_t->unsigned short
        /// </summary>
        public ushort len;

        /// <summary>
        /// uint8_t->unsigned char,type=5
        /// </summary>
        public byte type;

        /// <summary>
        /// uint8_t->unsigned char,ver=3
        /// </summary>
        public byte ver;

        public byte[] ToBytes()
        {
            byte[] ans = null;
            MemoryStream ms = null;
            BinaryWriter bw = null;
            try
            {
                ms = new MemoryStream();
                bw = new BinaryWriter(ms);
                bw.Seek(0, SeekOrigin.Begin);
                bw.Write(this.len);
                bw.Write(this.type);
                bw.Write(this.ver);
                ans = ms.ToArray();
            }
            catch (Exception er)
            {
                ans = null;
                Console.Write(er.Message);
            }
            finally
            {
                if (ms != null)
                {
                    ms.Close();
                    ms.Dispose();
                }
                if (bw != null)
                {
                    bw.Close();
                }
            }
            return ans;
        }

    }

    /// <summary>
    /// 友上协议的消息体
    /// </summary>
    [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct YoSunRecord
    {
        /// <summary>
        /// 用于存储图片数据长度、行驶方向和车道号
        /// </summary>
        public uint bitvector1;

        /// <summary>
        /// 日期，UTC时间
        /// </summary>
        public uint date;

        /// <summary>
        /// 存储红灯时间redLight和设备类型device
        /// </summary>
        public ushort bitvector2;

        /// <summary>
        /// 速度，15-999
        /// </summary>
        public ushort speed;

        /// <summary>
        /// 路口代码
        /// </summary>
        public ushort pasCode;

        /// <summary>
        /// 存储限速值threshold和号牌号码1 plate1
        /// 无车牌时，plate1为0
        /// </summary>
        public ushort bitvector3;

        /// <summary>
        /// 车牌后6位字母
        /// 无车牌时，则全部为0
        /// </summary>
        [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 6, ArraySubType = UnmanagedType.I1)]
        public char[] plate2;

        /// <summary>
        /// 存储车长carLen、车身颜色color、超速比overspeed、是否导出writeout、是否已处罚punish
        /// </summary>
        public uint bitvector4;

        /// <summary>
        /// 存储超速放宽比例osratio、抓怕位置capPos、识别状态recStatus、违章原因preassign
        /// </summary>
        public uint bitvector5;

        /// <summary>
        /// 违章原因，具体定义见后面
        /// </summary>
        public ushort reason;

        /// <summary>
        /// 未知
        /// </summary>
        public byte productType;

        /// <summary>
        /// 转向代码: 1 左拐，2 直行，3 右拐，4 直左，5 直右
        /// </summary>
        public byte turnCode;

        /// <summary>
        /// 图片总张数
        /// </summary>
        public byte picCount;

        /// <summary>
        /// 当前图片序号
        /// </summary>
        public byte picOrder;

        /// <summary>
        /// 闯红灯时间，精确到0.1秒
        /// </summary>
        public ushort redLightTime;

        /// <summary>
        /// 未知
        /// </summary>
        public ushort ta1;

        /// <summary>
        /// 未知
        /// </summary>
        public ushort ta2;

        /// <summary>
        /// 图片类型，是否闯红灯，0为闯红灯，1为卡口
        /// </summary>
        public byte picType;

        /// <summary>
        /// 0 正常, 1 逆行
        /// </summary>
        public byte state;

        /// <summary>
        /// 存储设备IP地址
        /// </summary>
        [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 16, ArraySubType = UnmanagedType.I1)]
        public char[] ip;

        /// <summary>
        /// 图片存放路径
        /// </summary>
        //[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 256, ArraySubType = UnmanagedType.I1)]
        //public char[] path;

        public byte[] path;

        /// <summary>
        /// 车牌小图片文件大小：0 无车牌，其它 车牌大小
        /// </summary>
        /// <value>
        /// 0 无车牌，其它 车牌大小
        /// </value>
        public uint plateSize;

        /// <summary>
        /// 红名单告警： 0 不是，1是
        /// </summary>
        public byte vip;

        /// <summary>
        /// 模糊车牌告警： 0不是，1是
        /// </summary>
        public byte fuzzy;

        /// <summary>
        /// 布控信息，utf8编码
        /// </summary>
        [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 256, ArraySubType = UnmanagedType.I1)]
        public char[] bkInfo;

        /// <summary>
        /// 区域代码
        /// </summary>
        [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 8, ArraySubType = UnmanagedType.I1)]
        public char[] areaCode;

        /// <summary>
        /// 系统编号
        /// </summary>
        [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 8, ArraySubType = UnmanagedType.I1)]
        public char[] sysNum;

        /// <summary>
        /// 过车时间
        /// </summary>
        public ushort ms;
        
        /// <summary>
        /// 车身颜色
        /// </summary>
        public ushort vbColor;

        /// <summary>
        /// 图片数据长度
        /// </summary>
        public uint fileSize
        {
            get
            {
                //todo 
                return ((uint)((this.bitvector1 & 16777215u)));
            }
            set
            {
                this.bitvector1 = ((uint)((value | this.bitvector1)));
            }
        }

        /// <summary>
        /// 方向：01-由东向西,02-由东向南,03-由东向北,04-由南向北,05-由南向西,06-由南向东,;07-由西向东,08-由西向北,09-由西向南,10-由北向南,11-由北向东,12-由北向西,13-进城,14-出城
        /// </summary>
        public uint direction
        {
            get
            {
                return ((uint)(((this.bitvector1 & 251658240u)
                            / 16777216)));
            }
            set
            {
                this.bitvector1 = ((uint)(((value * 16777216)
                            | this.bitvector1)));
            }
        }
        /// <summary>
        /// 车道编号
        /// </summary>
        public uint lane
        {
            get
            {
                return ((uint)(((this.bitvector1 & 4026531840u)
                            / 268435456)));
            }
            set
            {
                this.bitvector1 = ((uint)(((value * 268435456)
                            | this.bitvector1)));
            }
        }
        /// <summary>
        /// 整个红灯时间，精确到秒
        /// </summary>
        public ushort redLight
        {
            get
            {
                return ((ushort)((this.bitvector2 & 1023u)));
            }
            set
            {
                this.bitvector2 = ((ushort)((value | this.bitvector2)));
            }
        }

        /// <summary>
        /// 设备类型：31-高清电子警察 32-高清卡口型电子警察33-高清卡口,34-高清固定超速,35-高清移动超速，36-高清单行线逆行
        /// </summary>
        public ushort device
        {
            get
            {
                return ((ushort)(((this.bitvector2 & 64512u)
                            / 1024)));
            }
            set
            {
                this.bitvector2 = ((ushort)(((value * 1024)
                            | this.bitvector2)));
            }
        }
        /// <summary>
        /// 限速值
        /// </summary>
        public ushort threshold
        {
            get
            {
                return ((ushort)((this.bitvector3 & 511u)));
            }
            set
            {
                this.bitvector3 = ((ushort)((value | this.bitvector3)));
            }
        }

        /// <summary>
        /// 车牌首字母代码，具体定义见后面
        /// </summary>
        public ushort plate1
        {
            get
            {
                return ((ushort)(((this.bitvector3 & 65024u)
                            / 512)));
            }
            set
            {
                this.bitvector3 = ((ushort)(((value * 512)
                            | this.bitvector3)));
            }
        }
        /// <summary>
        /// 车辆长度，单位cm
        /// </summary>
        public uint carLen
        {
            get
            {
                return ((uint)((this.bitvector4 & 4095u)));
            }
            set
            {
                this.bitvector4 = ((uint)((value | this.bitvector4)));
            }
        }

        /// <summary>
        /// 车牌颜色：1 蓝色，2 黑色，3 黄色，4 白色，
        /// </summary>
        public uint color
        {
            get
            {
                return ((uint)(((this.bitvector4 & 258048u)
                            / 4096)));
            }
            set
            {
                this.bitvector4 = ((uint)(((value * 4096)
                            | this.bitvector4)));
            }
        }

        /// <summary>
        /// 超速比：1 0-20%，2 20%-50%, 3 50%-70%, 4 70%以上
        /// </summary>
        public uint overspeed
        {
            get
            {
                return ((uint)(((this.bitvector4 & 66846720u)
                            / 262144)));
            }
            set
            {
                this.bitvector4 = ((uint)(((value * 262144)
                            | this.bitvector4)));
            }
        }

        /// <summary>
        /// 是否导出
        /// </summary>
        public uint writeout
        {
            get
            {
                return ((uint)(((this.bitvector4 & 469762048u)
                            / 67108864)));
            }
            set
            {
                this.bitvector4 = ((uint)(((value * 67108864)
                            | this.bitvector4)));
            }
        }


        /// <summary>
        /// 是否已处罚：0未处罚，1已处罚
        /// </summary>
        public uint punish
        {
            get
            {
                return ((uint)(((this.bitvector4 & 3758096384u)
                            / 536870912)));
            }
            set
            {
                this.bitvector4 = ((uint)(((value * 536870912)
                            | this.bitvector4)));
            }
        }

        /// <summary>
        /// 限速比: 在限速值上放宽范围比例
        /// </summary>
        public uint osratio
        {
            get
            {
                return ((uint)((this.bitvector5 & 127u)));
            }
            set
            {
                this.bitvector5 = ((uint)((value | this.bitvector5)));
            }
        }
        /// <summary>
        /// 抓拍位置: 1-车头，2-侧面, 3-车尾,4-顶部
        /// </summary>
        public uint capPos
        {
            get
            {
                return ((uint)(((this.bitvector5 & 1920u)
                            / 128)));
            }
            set
            {
                this.bitvector5 = ((uint)(((value * 128)
                            | this.bitvector5)));
            }
        }
        /// <summary>
        /// 识别状态
        /// </summary>
        public uint recStatus
        {
            get
            {
                return ((uint)(((this.bitvector5 & 30720u)
                            / 2048)));
            }
            set
            {
                this.bitvector5 = ((uint)(((value * 2048)
                            | this.bitvector5)));
            }
        }
        /// <summary>
        /// 违章原因
        /// </summary>
        public uint preassign
        {
            get
            {
                return ((uint)(((this.bitvector5 & 4294934528u)
                            / 32768)));
            }
            set
            {
                this.bitvector5 = ((uint)(((value * 32768)
                            | this.bitvector5)));
            }
        }

        /// <summary>
        /// 生成友上消息体的字节数组
        /// </summary>
        /// <returns>友上消息体字节数组</returns>
        public byte[] ToBytes()
        {
            byte[] ans = null;
            MemoryStream memoryStream = null;
            BinaryWriter bw = null;
            try
            {
                memoryStream = new MemoryStream();
                bw = new BinaryWriter(memoryStream);
                bw.Seek(0, SeekOrigin.Begin);
                bw.Write(this.bitvector1);
                bw.Write(this.date);
                bw.Write(this.bitvector2);
                bw.Write(this.speed);
                bw.Write(this.pasCode);
                bw.Write(this.bitvector3);
                bw.Write(this.plate2, 0, 6);
                bw.Write(this.bitvector4);
                bw.Write(this.bitvector5);
                bw.Write(this.reason);
                bw.Write(this.productType);
                bw.Write(this.turnCode);
                bw.Write(this.picCount);
                bw.Write(this.picOrder);
                bw.Write(this.redLightTime);
                bw.Write(this.ta1);
                bw.Write(this.ta2);
                bw.Write(this.picType);
                bw.Write(this.state);
                bw.Write(this.ip, 0, 16);
                bw.Write(this.path, 0, 256);
                bw.Write(this.plateSize);
                bw.Write(this.vip);
                bw.Write(this.fuzzy);
                bw.Write(this.bkInfo, 0, 256);
                bw.Write(this.areaCode, 0, 8);
                bw.Write(this.sysNum, 0, 8);
                bw.Write(this.ms);
                bw.Write(this.vbColor);
                ans = memoryStream.ToArray();
            }
            catch (Exception er)
            {
                ans = null;
                Console.Write(er.Message);
            }
            finally
            {
                if (memoryStream != null)
                {
                    memoryStream.Close();
                    memoryStream.Dispose();
                }
                if (bw != null)
                {
                    bw.Close();
                }
            }
            return ans;
        }

    }

    /// <summary>
    /// 友上协议的车牌数据
    /// </summary>
    [StructLayoutAttribute(LayoutKind.Sequential)]
    public struct YoSunPlate
    {
        public byte[] byteYosunPlate { get; set; }

        public byte[] ToBytes()
        {
            return byteYosunPlate;
        }
    }

    /// <summary>
    /// 友上协议的完整消息
    /// 用于向友上平台发送
    /// </summary>
    [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct YoSunStruct
    {
        /// <summary>
        /// 友上协议的消息体
        /// </summary>
        public YoSunHead_t YSHead;
        /// <summary>
        /// 友上协议的消息体
        /// </summary>
        public YoSunRecord YSRecord;
        /// <summary>
        /// 友上协议的车牌数据
        /// </summary>
        public YoSunPlate YSPlate;
        /// <summary>
        /// 友上协议的文件名
        /// </summary>
        public string fileName
        {
            get
            {
                return CreateName();
            }
        }

        /// <summary>
        /// 生成友上协议的完整消息的字节数组
        /// </summary>
        /// <returns>友上协议的完整消息的字节数组</returns>
        public byte[] ToBytes()
        {
            byte[] byteYoSun = YoSun.CByteArray(YSHead.ToBytes(), YSRecord.ToBytes(), YSPlate.ToBytes());
            return byteYoSun;
        }

        /// <summary>
        /// 从友上自身的记录结构体中生成自身的文件名
        /// </summary>
        /// <returns></returns>
        public string CreateName()
        {
            string strName = string.Empty;

            //友上的文件名
            List<string> listYosun = new List<string>();

            //设备名
            listYosun.Add(YSRecord.device.ToString());
            //路口代码
            listYosun.Add(string.Format("{0:d2}", YSRecord.pasCode));
            //方向代码
            listYosun.Add(string.Format("{0:d2}", YSRecord.direction));
            //车道
            listYosun.Add(string.Format("{0:d1}", YSRecord.lane));
            //时间
            DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
            dtStart = dtStart.AddSeconds(YSRecord.date);

            listYosun.Add(string.Format("{0:yyyyMMddHHmmss}", dtStart));
            //红灯
            listYosun.Add(string.Format("{0:d2}", YSRecord.redLight));
            //速度
            listYosun.Add(string.Format("{0:d3}", YSRecord.speed));
            //限速值
            listYosun.Add(string.Format("{0:d3}", YSRecord.threshold));
            //限速比
            listYosun.Add(string.Format("{0:d2}", YSRecord.osratio));
            //车长
            listYosun.Add(string.Format("{0:d4}", YSRecord.carLen));
            //车牌
            string strPlate1 = string.Format("{0:d2}", YSRecord.plate1);

            string strPlate2 = "";
            if (YSRecord.plate2 != null)
            {
                for (int i = 0; i < YSRecord.plate2.Length; i++)
                {
                    if (YSRecord.plate2[i] != '\0')
                    {
                        strPlate2 += YSRecord.plate2[i];
                    }
                    else
                    {
                        strPlate2 += "0";
                    }
                }
            }
            else
            {
                strPlate2 = "000000";
            }

            listYosun.Add(strPlate1 + strPlate2);

            //车牌颜色
            listYosun.Add(string.Format("{0:d1}", YSRecord.color));
            //抓拍位置
            listYosun.Add(string.Format("{0:d1}", YSRecord.capPos));
            //识别状态
            listYosun.Add(string.Format("{0:d1}", YSRecord.recStatus));
            //超速比 00
            listYosun.Add(string.Format("{0:d2}", YSRecord.overspeed));
            //违法原因 0000
            listYosun.Add(string.Format("{0:d2}", YSRecord.preassign) + string.Format("{0:d2}", YSRecord.reason));
            //是否导出 0
            listYosun.Add(string.Format("{0:d1}", YSRecord.writeout));
            //是否惩罚 0
            listYosun.Add(string.Format("{0:d1}", YSRecord.punish));
            //转向代码 1
            listYosun.Add(string.Format("{0:d1}", YSRecord.turnCode));
            //图片顺序(1) 0
            listYosun.Add(YSRecord.picOrder.ToString());
            //图片总数(1) 0
            listYosun.Add(YSRecord.picCount.ToString());
            //红灯时间(3)逆行(1) 0000
            listYosun.Add("0000");
            //第一位为卡口或闯红灯标志,这与其picType字段相反,1为闯红灯，2为卡口
            //vip字段取值说明：红名单告警，0 不是，1是
            //fuzzy字段取值说明：模糊车牌告警：0不是，1是
            //state字段取值说明：0 正常, 1 逆行
            //0000
            listYosun.Add(string.Format("{0:d1}", ((YSRecord.picType.ToString() == "0") ? 1 : 0)) + "000");
            //行政区域(4) 3208
            listYosun.Add("0000");
            //行政区域(2)图片时间(2) 3032
            listYosun.Add("0000");
            //车身颜色(1)路口代码百位(1)预留(2) 1000
            listYosun.Add(string.Format("{0:d1}", YSRecord.vbColor) + "000");

            strName = YoSun.conString(listYosun);

            return strName;
        }

    }

    //todo 提供转成友上的接口
    public class YoSun
    {

        /// <summary>
        /// 向友上平台发送符合友上协议的数据
        /// </summary>
        /// <param name="sendIP">要发送的IP地址</param>
        /// <param name="sendPort">要发送的端口号</param>
        /// <param name="byteArray">要发送的字节数组内容</param>
        /// <returns>是否发送成功</returns>
        public bool send(IPAddress sendIP, int sendPort, byte[] byteArray)
        {

            try
            {
                TcpClient tcpClientYousun = new TcpClient(sendIP.ToString(), sendPort);
                NetworkStream networkStream = tcpClientYousun.GetStream();

                BinaryWriter bw = new BinaryWriter(networkStream, Encoding.UTF8);

                bw.Write(byteArray);
                return true;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return false;
            }

        }

        /// <summary>
        /// 上传到友上的平台服务器，老版的dll用到
        /// </summary>
        public void upLoad(string dstIP, string dstPort, byte[] head, byte[] message, string picPath, string platePicPath)
        {

        }

        /// <summary>
        /// 合并字节数组
        /// </summary>
        /// <param name="srcArray1">第一个字节数组</param>
        /// <param name="srcArray2">第二个字节数组</param>
        /// <returns></returns>
        public static byte[] CByteArray(byte[] srcArray1, byte[] srcArray2)
        {
            if (srcArray1 == null)
            {
                return srcArray2;
            }

            if (srcArray2 == null)
            {
                return srcArray1;
            }

            if (srcArray1 == null && srcArray2 == null)
            {
                return null;
            }

            //根据要合并的两个数组元素总数新建一个数组
            byte[] newArray = new byte[srcArray1.Length + srcArray2.Length];

            //把第一个数组复制到新建数组
            Array.Copy(srcArray1, 0, newArray, 0, srcArray1.Length);

            //把第二个数组复制到新建数组
            Array.Copy(srcArray2, 0, newArray, srcArray1.Length, srcArray2.Length);

            return newArray;
        }

        public static byte[] CByteArray(byte[] srcArray1, byte[] srcArray2, byte[] srcArray3)
        {
            return CByteArray(CByteArray(srcArray1, srcArray2), srcArray3);
        }

        /// <summary>
        /// 拼合文件名字符串
        /// </summary>
        /// <param name="listString"></param>
        /// <returns></returns>
        public static string conString(List<string> listString)
        {
            string conString = "";
            string spliter = "_";
            foreach (string ele in listString)
            {
                conString += ele + spliter;
            }
            conString = conString.Remove(conString.Length - 1) + ".jpg";
            return conString;
        }

        /// <summary>
        /// 获取本机的IP
        /// </summary>
        /// <returns>本机的IP</returns>
        public static string getHostIP()
        {
            IPHostEntry ipHostEntry = Dns.GetHostEntry(System.Net.Dns.GetHostName());
            for (int i = 0; i <= ipHostEntry.AddressList.Length; i++)
            {
                //AddressFamily.InterNetwork代表IPV4地址，不包含IPV6
                if (ipHostEntry.AddressList[i].AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                {
                    return ipHostEntry.AddressList[i].ToString();
                }

            }
            return "get FAIL!";
        }

    }

     
}
